import re
from random import randint

from django import http
from django.contrib.auth import login, logout
from django.contrib.auth import authenticate
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse
from django.shortcuts import render, redirect
from django.template.backends import jinja2
from django.urls import reverse
from django.views import View
from django.contrib.auth.backends import ModelBackend
from django_redis import get_redis_connection
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from apps.goods.models import SKU
from apps.users.utils import check_verify_token
from utils.response_code import RETCODE
import json
from meiduo_mail import settings
from django.core.mail import send_mail

# Create your views here.
from apps.users.models import User, Address

from celery_tasks.email.tasks import send_active_email
import logging
from apps.carts.utils import merge_cookie_to_redis
from apps.oauth.utils import generic_openid_token, check_openid_token
from celery_tasks.sms.tasks import send_sms_code


class RegisterView(View):
    def get(self, request):

        return render(request, 'register.html')

    def post(self, request):
        username = request.POST.get('username')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        mobile = request.POST.get('mobile')

        if not all([username, password, password2, mobile]):
            return http.HttpResponseBadRequest('参数不全')
        if not re.match(r'[a-zA-Z0-9_-]{5,20}', username):
            return http.HttpResponseBadRequest('用户名不符合规则')
        if not re.match(r'[a-zA-Z0-9]{8,20}', password):
            return http.HttpResponseBadRequest('密码不符合规则')
        if password != password2:
            return http.HttpResponseBadRequest('两次密码不一致')
        if not re.match(r'1[3-9]\d{9}', mobile):
            return http.HttpResponseBadRequest('手机号不符合规则')

        user = User.objects.create_user(
            username=username,
            password=password,
            mobile=mobile
        )

        login(request, user)
        path = reverse('contents:index')
        print('0')
        response = redirect(path)
        print('1')
        return response
        # return HttpResponse('注册成功')


class UsernameCountView(View):
    def get(self, request, username):
        count = User.objects.filter(username=username).count()
        return http.JsonResponse({'count': count})


class MobileCountView(View):
    def get(self, request, mobile):
        count = User.objects.filter(mobile=mobile).count()
        return http.JsonResponse({'count': count})


class LoginView(View):
    def get(self, request):
        return (render(request, 'login.html'))

    def post(self, request):
        username = request.POST.get('username')
        password = request.POST.get('pwd')
        remembered = request.POST.get('remembered')
        next = request.GET.get('next')
        if not all([username, password]):
            return http.HttpResponseBadRequest('参数不全')
        if not re.match(r'[a-zA-Z0-9_]{5,20}', username):
            return http.HttpResponseBadRequest('用户名不符合规则')
        if not re.match(r'[a-zA-Z0-9_]{8,20}', password):
            return http.HttpResponseBadRequest('密码不符合规则')
        user = authenticate(username=username, password=password)

        if user is None:
            return http.HttpResponseBadRequest('账号或密码错误')

        login(request, user)
        if remembered == 'on':
            request.session.set_expiry(None)
        else:
            request.session.set_expiry(0)

        if next:
            response = redirect(next)
        else:
            response = redirect(reverse('contents:index'))
        response.set_cookie('username', user.username)

        merge_cookie_to_redis(request, user, response)
        return response


class LogoutView(View):
    def get(self, request):
        logout(request)

        response = redirect(reverse('contents:index'))
        response.delete_cookie('username')
        return response


class UserInfoView(LoginRequiredMixin, View):
    login_url = '/login/'

    def get(self, request):
        context = {
            'username': request.user.username,
            'id': request.user.id,
            'mobile': request.user.mobile,
            'email': request.user.email,
            'email_active': request.user.email_active,
        }

        return render(request, 'user_center_info.html', context=context)


class EmailView(View):
    def put(self, request):
        user = request.user
        body = request.body
        body_str = body.decode()
        data = json.loads(body_str)
        email = data.get('email')

        if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '邮箱格式不正确'})
        try:
            user.email = email
            user.save()
        except Exception as e:
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '保存失败'})

        send_active_email.delay(email, request.user.id)

        return http.JsonResponse({'code': RETCODE.OK})


class EmailActiveView(View):
    def get(self, request):
        token = request.GET.get('token')
        if token is None:
            return http.HttpResponseBadRequest('参数不全')
        user_id = check_verify_token(token)
        if user_id is None:
            return http.HttpResponseBadRequest('参数错误')
        try:
            user = User.objects.get(id=user_id)
        except User.DoesNotExist:
            return http.HttpResponseBadRequest('没有此用户')
        user.email_active = True
        user.save()
        return redirect(reverse('users:center'))


class UserCenterSiteView(LoginRequiredMixin, View):
    def get(self, request):
        addresses = Address.objects.filter(user=request.user, is_deleted=False)
        address_list = []
        for address in addresses:
            address_list.append({
                "id": address.id,
                "title": address.title,
                "receiver": address.receiver,
                "province": address.province.name,
                "province_id": address.province_id,
                "city": address.city.name,
                "city_id": address.city_id,
                "district": address.district.name,
                "district_id": address.district_id,
                "place": address.place,
                "mobile": address.mobile,
                "tel": address.tel,
                "email": address.email,
            })
        context = {
            'default_address_id': request.user.default_address_id,
            'addresses': address_list,
        }
        return render(request, 'user_center_site.html', context=context)


logger = logging.getLogger('django')


class CreateAddressView(View):
    def post(self, request):
        json_dict = json.loads(request.body.decode())
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')

        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return http.HttpResponseBadRequest('参数不全')
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseBadRequest('请输入正确的手机号')
        if tel:
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.HttpResponseBadRequest('请输入正确的固定电话')
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return http.HttpResponseBadRequest('请输入正确的邮箱地址')
        try:
            address = Address.objects.create(
                user=request.user,
                title=receiver,
                receiver=receiver,
                province_id=province_id,
                city_id=city_id,
                district_id=district_id,
                place=place,
                mobile=mobile,
                tel=tel,
                email=email,
            )
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '导入数据库失败,请稍后再试'})
        new_address = {
            'id': address.id,
            "title": address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '新增地址成功', 'address': new_address})


class AddressUpdateView(View):
    def put(self, request, address_id):
        json_dict = json.loads(request.body.decode())
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')

        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return http.HttpResponseBadRequest('参数不全')
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseBadRequest('请输入正确的手机号')
        if tel:
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.HttpResponseBadRequest('请输入正确的固定电话')
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return http.HttpResponseBadRequest('请输入正确的邮箱地址')
        try:
            result = Address.objects.filter(pk=address_id).update(
                user=request.user,
                title=receiver,
                receiver=receiver,
                province_id=province_id,
                city_id=city_id,
                district_id=district_id,
                place=place,
                mobile=mobile,
                tel=tel,
                email=email,
            )
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '导入数据库失败,请稍后再试'})
        if result == 0:
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '导入数据库失败,请稍后再试'})

        address = Address.objects.get(pk=address_id)
        updata_data = {
            'id': address.id,
            "title": address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '更新成功', 'address': updata_data})

    def delete(self, request, address_id):
        try:
            address = Address.objects.get(pk=address_id)
            address.is_deleted = True
            address.save()
        except Address.DoesNotExist:
            return http.HttpResponseBadRequest({'code': RETCODE.NODATAERR, 'errmsg': '没有此用户'})
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})


class ChangePasswordView(LoginRequiredMixin, View):
    def get(self, request):
        return render(request, 'user_center_pass.html')

    def post(self, request):
        old_password = request.POST.get('old_password')
        new_password = request.POST.get('new_password')
        new_password2 = request.POST.get('new_password2')

        if not all([old_password, new_password, new_password2]):
            return http.HttpResponseBadRequest('参数不全')
        if not re.match(r'^[0-9A-Za-z]{8,20}$', new_password):
            return http.HttpResponseBadRequest('您输入的密码格式有误，请输入8-20位密码')
        if new_password != new_password2:
            return http.HttpResponseBadRequest('两次输入的密码不一致')
        if not request.user.check_password(old_password):
            return render(request, 'user_center_pass.html', {'origin_password_errmsg': '原始密码错误'})
        try:
            request.user.set_password(new_password)
            request.user.save()
        except Exception as e:

            logger.error(e)
            return render(request, 'user_center_pass.html', {'change_password_errmsg': '修改密码失败'})

        logout(request)

        response = redirect(reverse('users:login'))

        response.delete_cookie('username')

        return response


class DefaultAddressView(LoginRequiredMixin, View):
    def put(self, request, address_id):
        try:
            address = Address.objects.get(id=address_id)
            request.user.default_address_id = address
            request.user.save()
        except Exception as e:
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '设置失败'})
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '设置成功'})


class UpdateTitleAddressView(LoginRequiredMixin, View):
    def put(self, request, address_id):
        json_list = json.loads(request.body.decode())
        title = json_list.get('title')

        try:
            address = Address.objects.get(id=address_id)
            address.title = title
            address.save()
        except Exception as  e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '修改失败'})
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '修改成功'})


class HistroyView(LoginRequiredMixin, View):
    def post(self, request):
        data = json.loads(request.body.decode())
        sku_id = data.get('sku_id')
        try:
            SKU.objects.get(pk=sku_id)
        except Exception as e:
            return http.JsonResponse({'code': RETCODE.DBERR, 'mrrmsg': '商品不存在'})
        redis_conn = get_redis_connection('history')
        redis_conn.lrem('history:%s' % request.user.id, 0, sku_id)
        redis_conn.lpush('history:%s' % request.user.id, sku_id)
        redis_conn.ltrim('history:%s' % request.user.id, 0, 4)
        return http.JsonResponse({'code': RETCODE.OK, 'mrrmsg': 'ok'})

    def get(self, request):
        redis_conn = get_redis_connection('history')
        ids = redis_conn.lrange('history:%s' % request.user.id, 0, 4)
        skus = []
        for id in ids:
            sku = SKU.objects.get(pk=id)
            skus.append({
                'id': sku.id,
                'name': sku.name,
                'default_image_url': sku.default_image.url,
                'price': sku.price
            })

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'ok', 'skus': skus})


class FindPasswordView(View):
    def get(self, request):
        return render(request, 'find_password.html')


class FindPwd(View):
    def get(self, request, username):
        # username = request.GET.get('username')
        image_code = request.GET.get('text')
        image_code_id = request.GET.get('image_code_id')
        if not all([username, image_code_id]):
            return http.HttpResponseBadRequest('参数不全')
        try:
            conn = get_redis_connection('code')
            redis_code = conn.get('img:%s' % image_code_id)
            if redis_code is None:
                return http.HttpResponseBadRequest('验证码已过期')
            if redis_code.decode().lower() != image_code.lower():
                return http.HttpResponseBadRequest('图片验证码输入错误')
            conn.delete('img:%s' % image_code)
        except Exception as e:
            return http.HttpResponseBadRequest('redis链接错误')
        try:
            if re.match('^1[3-9]\d{9}$', username):
                user = User.objects.get(mobile=username)
                mobile = user.mobile

            else:
                user = User.objects.get(username=username)
        except User.DoesNotExist:
            return None
        access_token = generic_openid_token(user.mobile)

        return http.JsonResponse({
            'mobile': user.mobile,
            'access_token': access_token
        })


class Sendmessige(View):
    def get(self, request):
        redis_conn = get_redis_connection('code')
        access_token = request.GET.get('access_token')
        user_id = check_openid_token(access_token)
        try:
            user = User.objects.get(mobile=user_id)
            mobile = user.mobile
        except Exception as e:
            pass
        sms_codes = '%06d' % randint(0, 999999)
        redis_conn.setex('sms_%s' % mobile, 600, sms_codes)
        send_sms_code.delay(mobile, sms_codes)
        return http.HttpResponse('ok')


class ChangePwd(View):
    def get(self, request, username):
        try:
            user = User.objects.get(username=username)
            mobile = user.mobile
        except Exception as e:
            pass
        mobile_code_client = request.GET.get('sms_code')
        redis_conn = get_redis_connection('code')
        mobile_code = redis_conn.get('sms_%s' % mobile)
        if mobile_code is None:
            return http.HttpResponseBadRequest('验证码已过期')
        mobile_code = mobile_code.decode()
        if mobile_code != mobile_code_client:
            return http.HttpResponseBadRequest('验证码有误')
        access_token = generic_openid_token(user.mobile)
        return http.JsonResponse({
            'user_id': user.id,
            'access_token': access_token,
        })


class NewPwd(View):
    def post(self, request, user_id):
        data = json.loads(request.body.decode())
        access_token = data.get('access_token')
        mobile = check_openid_token(access_token)
        try:
            user = User.objects.get(mobile=mobile)

            mobile = user.mobile
            # user_id = user.id
        except Exception as e:
            return http.HttpResponseBadRequest('有误')
        password = data.get('password')
        password2 = data.get('password2')
        if not all([password, password2]):
            return http.HttpResponseBadRequest('参数不全')
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseBadRequest('您输入的密码格式有误，请输入8-20位密码')
        if password != password2:
            return http.HttpResponseBadRequest('两次输入的密码不一致')
        try:
            user.set_password(password)
            user.save()
        except Exception as e:
            return http.HttpResponseBadRequest('有误')
        return http.HttpResponse('ok')
